#include "rational.h"

ostream& operator<< (ostream& out, Rational rat)
{
    if (rat.numerator == 0)
        out << 0;
    else
        if (rat.is_signed)
            out << "-" << abs (rat.num ()) << "/" << abs (rat.denom ());
        else
            out << abs (rat.num ()) << "/" << abs (rat.denom ());
    return out;
}

Rational::Rational (int re, int im)
{
    numerator = 1;
    denominator = 1;
    set_numerator (re);
    set_denominator (im);
}

Rational& Rational::operator+ (Rational second)
{
    this->set_numerator (this->num () * second.denom () 
                            + second.num () * this->denom ());
    this->set_denominator (this->denom ()  * second.denom ()); 
    return *this;
}
    
Rational& Rational::operator- (Rational second)
{
    this->set_numerator (this->num () * second.denom () 
                            - second.num () * this->denom ());
    this->set_denominator (this->denom ()  * second.denom ()); 
    return *this;
}

Rational& Rational::operator* (Rational second)
{
    this->set_numerator (this->num () * second.num ());
    this->set_denominator (this->denom () * second.denom ());
    return *this;
}

Rational& Rational::operator/ (Rational second)
{
    this->set_numerator (this->num () * second.denom ());
    this->set_denominator (this->denom () * second.num ());
    return *this;
}


void Rational::set_numerator (int a)
{
    numerator = a;
    reduce ();
}
    
void Rational::set_denominator (int b)
{
    if (b == 0)
        denominator = 1;
    else
        denominator = b;

    reduce ();
}

int Rational::num ()
{
    return numerator;
}

int Rational::denom ()
{
    return denominator;
}

double Rational::decimal ()
{
    return (double)(numerator)/denominator;
}

void Rational::reduce ()
{
    if (numerator == 0)
    {
        is_signed = false;
        denominator = 1;
        return;
    }

    if (denominator == 0) denominator = 1;
    if ((numerator < 0 && denominator < 0) || 
        (numerator > 0 && denominator > 0))
        is_signed = false;
    else if ((numerator < 0 && denominator > 0) || 
             (numerator > 0 && denominator < 0))
        is_signed = true;

    int gcd_num = gcd (numerator, denominator);
    numerator /= gcd_num;
    denominator /= gcd_num;
}

int Rational::gcd (int a, int b)
{
    if (a < b) swap(a,b);
    while (1) {
        if (a % b == 0) 
            return b;
        else {
            int foo = b;
            b = a % b;
            a = foo;
        }
    }
    return b;
}

       
